﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;

namespace Learun.Util
{
    /// <summary>
    /// 版 本 PIT-ADMS V7.0.3 敏捷开发框架
    /// Copyright (c) 2013-2018 Hexagon PPM
    /// 创建人：研发部
    /// 日 期：2017.03.04
    /// 描 述：常用公共类
    /// </summary>
    public static class CommonHelper
    {
        #region Stopwatch计时器
        /// <summary>
        /// 计时器开始
        /// </summary>
        /// <returns></returns>
        public static Stopwatch TimerStart()
        {
            Stopwatch watch = new Stopwatch();
            watch.Reset();
            watch.Start();
            return watch;
        }
        /// <summary>
        /// 计时器结束
        /// </summary>
        /// <param name="watch">Stopwatch</param>
        /// <returns></returns>
        public static string TimerEnd(Stopwatch watch)
        {
            watch.Stop();
            double costtime = watch.ElapsedMilliseconds;
            return costtime.ToString();
        }
        #endregion

        #region 删除数组中的重复项
        /// <summary>
        /// 删除数组中的重复项
        /// </summary>
        /// <param name="values">重复值</param>
        /// <returns></returns>
        public static string[] RemoveDup(string[] values)
        {
            List<string> list = new List<string>();
            for (int i = 0; i < values.Length; i++)//遍历数组成员
            {
                if (!list.Contains(values[i]))
                {
                    list.Add(values[i]);
                };
            }
            return list.ToArray();
        }
        #endregion

        #region 自动生成日期编号
        /// <summary>
        /// 自动生成编号  201008251145409865
        /// </summary>
        /// <returns></returns>
        public static string CreateNo()
        {
            Random random = new Random();
            string strRandom = random.Next(1000, 10000).ToString(); //生成编号 
            string code = DateTime.Now.ToString("yyyyMMddHHmmss") + strRandom;//形如
            return code;
        }
        #endregion

        #region 生成0-9随机数
        /// <summary>
        /// 生成0-9随机数
        /// </summary>
        /// <param name="codeNum">生成长度</param>
        /// <returns></returns>
        public static string RndNum(int codeNum)
        {
            StringBuilder sb = new StringBuilder(codeNum);
            Random rand = new Random();
            for (int i = 1; i < codeNum + 1; i++)
            {
                int t = rand.Next(9);
                sb.AppendFormat("{0}", t);
            }
            return sb.ToString();

        }
        #endregion

        #region 删除最后一个字符之后的字符
        /// <summary>
        /// 删除最后结尾的一个逗号
        /// </summary>
        /// <param name="str">字串</param>
        /// <returns></returns>
        public static string DelLastComma(string str)
        {
            return str.Substring(0, str.LastIndexOf(","));
        }
        /// <summary>
        /// 删除最后结尾的指定字符后的字符
        /// </summary>
        /// <param name="str">字串</param>
        /// <param name="strchar">指定的字符</param>
        /// <returns></returns>
        public static string DelLastChar(string str, string strchar)
        {
            return str.Substring(0, str.LastIndexOf(strchar));
        }
        /// <summary>
        /// 删除最后结尾的长度
        /// </summary>
        /// <param name="str">字串</param>
        /// <param name="Length">删除长度</param>
        /// <returns></returns>
        public static string DelLastLength(string str, int Length)
        {
            if (string.IsNullOrEmpty(str))
                return "";
            str = str.Substring(0, str.Length - Length);
            return str;
        }
        #endregion
        /// <summary>
        /// 比较两个时间的日期部分是否相等
        /// </summary>
        /// <param name="date1"></param>
        /// <param name="date2"></param>
        /// <returns></returns>
        public static bool EqualsDate(DateTime? date1, DateTime? date2)
        {
            if (!date1.HasValue || !date2.HasValue) return false;
            DateTime Date1 = date1.Value;
            DateTime Date2 = date2.Value;
            return Date1.Year == Date2.Year && Date1.Month == Date2.Month && Date1.Day == Date2.Day;
        }

        /// <summary>
        /// 比较两个字符串的大小，用于排序
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public static int Compare(string x, string y)
        {
            var numRegex = new Regex("[0-9]+");
            var strRegex = new Regex("[a-zA-Z]+");
            var numMatch = numRegex.Match(x);
            var strMatch = strRegex.Match(x);
            var xn = new List<string>();
            do
            {
                if (numMatch.Success && strMatch.Success)
                {
                    if (numMatch.Index < strMatch.Index)
                    {
                        xn.Add(numMatch.Value);
                        numMatch = numMatch.NextMatch();
                    }
                    if (numMatch.Index > strMatch.Index)
                    {
                        xn.Add(strMatch.Value);
                        strMatch = strMatch.NextMatch();
                    }
                }
                if (numMatch.Success && !strMatch.Success)
                {
                    xn.Add(numMatch.Value);
                    numMatch = numMatch.NextMatch();
                }
                if (!numMatch.Success && strMatch.Success)
                {
                    xn.Add(strMatch.Value);
                    strMatch = strMatch.NextMatch();
                }
            } while (numMatch.Success || strMatch.Success);
            numMatch = numRegex.Match(y);
            strMatch = strRegex.Match(y);
            var yn = new List<string>();
            do
            {
                if (numMatch.Success && strMatch.Success)
                {
                    if (numMatch.Index < strMatch.Index)
                    {
                        yn.Add(numMatch.Value);
                        numMatch = numMatch.NextMatch();
                    }
                    if (numMatch.Index > strMatch.Index)
                    {
                        yn.Add(strMatch.Value);
                        strMatch = strMatch.NextMatch();
                    }
                }
                if (numMatch.Success && !strMatch.Success)
                {
                    yn.Add(numMatch.Value);
                    numMatch = numMatch.NextMatch();
                }
                if (!numMatch.Success && strMatch.Success)
                {
                    yn.Add(strMatch.Value);
                    strMatch = strMatch.NextMatch();
                }
            } while (numMatch.Success || strMatch.Success);
            for (int i = 0; i < Math.Max(xn.Count, yn.Count); i++)
            {
                if (xn.Count < i + 1) return -1;
                if (yn.Count < i + 1) return 1;
                if (numRegex.IsMatch(xn[i]) && numRegex.IsMatch(yn[i]))
                {
                    long a;
                    if (!long.TryParse(xn[i], out a))
                    {
                        a = long.MaxValue;
                    }
                    long b;
                    if (!long.TryParse(yn[i], out b))
                    {
                        b = long.MaxValue;
                    }
                    if (a < b)
                    {
                        return -1;
                    }
                    if (a > b)
                    {
                        return 1;
                    }
                }
                var res = xn[i].CompareTo(yn[i]);
                if (res != 0)
                {
                    return res;
                }
            }
            return 0;
        }

        /// <summary>
        /// 字符串转换
        /// </summary>
        /// <param name="obj"></param>
        public static string ConvertObjToString(object obj)
        {
            if (obj.IsEmpty() || obj == null)
            {
                return "";
            }
            return obj.ToString();
        }

        /// <summary>
        /// 字符串转换
        /// </summary>
        /// <param name="obj"></param>
        public static int ConvertObjToInt(object obj)
        {
            if (obj.IsEmpty() || obj == null)
            {
                return 0;
            }
            return obj.ToString() == "" ? 0 : Convert.ToInt32(obj);
        }
        /// <summary>
        /// 罗马数字转阿拉伯数字
        /// </summary>
        /// <param name="romanNumber"></param>
        public static int RomanToArabicConvert(string romanNumber)
        {
            // 定义罗马数字对应的阿拉伯数字值
            var romanValues = new Dictionary<char, int> {
                {'I', 1},
                {'V', 5},
                {'X', 10},
                {'L', 50},
                {'C', 100},
                {'D', 500},
                {'M', 1000}
            };

            int result = 0;
            for (int i = 0; i < romanNumber.Length - 1; i++)
            {
                if (romanValues[romanNumber[i]] >= romanValues[romanNumber[i + 1]])
                {
                    result += romanValues[romanNumber[i]];
                }
                else
                {
                    result -= romanValues[romanNumber[i]];
                }
            }

            return result + romanValues[romanNumber[romanNumber.Length - 1]];
        }
        /// <summary>
        /// 阿拉伯数字转罗马数字
        /// </summary>
        /// <param name="number"></param>
        public static string ConvertToRomanNumeral(int number)
        {
            if (number < 0 || number > 3999)
                throw new ArgumentOutOfRangeException();

            var romanSymbols = new Dictionary<int, string>
            {
                {1000, "M"},
                {500, "D"},
                {100, "C"},
                {50, "L"},
                {10, "X"},
                {5, "V"},
                {1, "I"}
            };

            StringBuilder resultBuilder = new StringBuilder();

            foreach (var symbol in romanSymbols)
            {
                while (number >= symbol.Key)
                {
                    resultBuilder.Append(symbol.Value);

                    number -= symbol.Key;
                }
            }

            return resultBuilder.ToString();
        }
        //Excel列字母转数字
        public static int ToIndex(string columnName)
        {
            if (!Regex.IsMatch(columnName.ToUpper(), @"[A-Z]+")) { throw new Exception("invalid parameter"); }

            int index = 0;
            char[] chars = columnName.ToUpper().ToCharArray();
            for (int i = 0; i < chars.Length; i++)
            {
                index += ((int)chars[i] - (int)'A' + 1) * (int)Math.Pow(26, chars.Length - i - 1);
            }
            return index - 1;
        }
        //Excel数字转列字母
        public static string ToName(int index)
        {
            if (index < 0) { throw new Exception("invalid parameter"); }

            List<string> chars = new List<string>();
            do
            {
                if (chars.Count > 0) index--;
                chars.Insert(0, ((char)(index % 26 + (int)'A')).ToString());
                index = (int)((index - index % 26) / 26);
            } while (index > 0);

            return String.Join(string.Empty, chars.ToArray());
        }
        #region 反射接口对象
        /// <summary>
        /// 
        /// </summary>
        /// <param name="assemblyPath"></param>
        /// <param name="className"></param>
        /// <returns></returns>
        public static ConstructorInfo GetConstructorInfo(string assemblyPath, string className)
        {
            ConstructorInfo conInfo = null;
            try
            {
                conInfo = Assembly.LoadFrom(assemblyPath).GetType(className).GetConstructor(new Type[0]);
            }
            catch { }

            return conInfo;
        }

        public static object GetConcretDataProvider(string className, string assemblyName)
        {
            object obj = null;
            try
            {
                string assemblyPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, string.Format(@"bin\{0}.dll", assemblyName));
                if (!File.Exists(assemblyPath))
                {
                    assemblyPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, string.Format(@"{0}.dll", assemblyName));
                }
                ConstructorInfo con = GetConstructorInfo(assemblyPath, className);

                obj = con.Invoke(null);
            }
            catch { }

            return obj;
        }

        public static bool InvokeGetProperty(object target, string propName, out object propToGet, out Exception exception)
        {
            propToGet = null;
            exception = null;
            Type targetType = target.GetType();
            MemberInfo[] methods =
                targetType.GetMember(propName, MemberTypes.Property, BindingFlags.Public | BindingFlags.Instance);
            if (methods.Length > 0) //找到了datasource属性
            {
                try
                {
                    propToGet = targetType.InvokeMember(propName,
                                                        BindingFlags.GetProperty, null, target,
                                                        new object[] { });

                    return true;
                }
                catch (Exception ex)
                {
                    exception = ex;
                    return false;
                }
            }
            exception = new ApplicationException(string.Format("未找到{0}属性", propName));
            return false;
        }
        #endregion
    }
}
